package com.ys.day32.p1FastJson模拟;

import java.lang.reflect.Field;

/**
 * 描述: 模拟FastJson 的超级简单实现
 *
 * @author CodeYang
 * @version 2021/1/18 15:15
 */
final public class JSON {

    /**
     * 把对象属性作为key,值作为value 返回一个 json str
     *
     * @param object
     * @return json  str
     * {"id":"101","name":"ys","address":"武汉","birth":"Mon Jan 18 15:27:42 CST 2021"}
     */
    public static String parseSimpleString(Object object) {
        // 1: 反射出Class对象
        Class<?> Clazz = object.getClass();
        // 2: 获取对象的对象Fileds 字段集合
        Field[] fields = Clazz.getDeclaredFields();
        // 3: 最终返回的Str
        StringBuilder sb = new StringBuilder(30);
        sb.append("{");
        try {
            for (int i = 0; i < fields.length; i++) {
                // 获得对象的key 与 value
                Field field = fields[i];
                // 暴力破解所有属性 的可访问性
                field.setAccessible(true);
                String key = field.getName();
                Object value = field.get(object);
                // 1 判断一下是不是第一个 key:value对象
                if (0 == i) {
                    sb.append("\"" + key + "\"" + ":" + "\"" + value + "\"");
                } else {
                    // 不是第一个 就需要在前面添加一个 ,
                    sb.append(",\"" + key + "\"" + ":" + "\"" + value + "\"");
                }
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return sb.append("}").toString();
    }


    /**
     * Json 有4种基本类型的数据
     * 1: number 数字
     * 2: str
     * 3; boolean
     * 4; null
     * -----
     * 先不处理嵌套 对象与集合的情况
     *
     * @param object
     * @return json  str
     * {"id":"101","name":"ys","address":"武汉","birth":"Mon Jan 18 15:27:42 CST 2021"}
     */
    public static String parseObjectToString(Object object) {
        // 1: 反射出Class对象
        Class<?> Clazz = object.getClass();
        // 2: 获取对象的对象Fileds 字段集合
        Field[] fields = Clazz.getDeclaredFields();
        // 3: 最终返回的Str
        StringBuilder sb = new StringBuilder(30);
        sb.append("{");
        try {
            for (int i = 0; i < fields.length; i++) {
                // 获得对象的key 与 value
                Field field = fields[i];
                // 暴力破解所有属性 的可访问性
                field.setAccessible(true);
                String key = field.getName();
                Object value = field.get(object);
                // 1 判断一下是不是第一个 key:value对象
                if (0 == i) {
                    sb.append("\"" + key + "\"" + ":" + isFormatCheckObjectType(value));
                } else {
                    sb.append(",\"" + key + "\"" + ":" + isFormatCheckObjectType(value));
                }
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return sb.append("}").toString();
    }

    /**
     * 用于检查传递进来的对象的数据类型,
     * 预设返回应该只有4种与 json的规则一致
     * 1: number 数字
     * *  2: str
     * *  3; boolean
     * *  4; null
     * 思路 : 使用 instanceof 来判断类型(包装类),
     * 但是 insranceof 只能用来判断包装类,也就是我们这里还处理不了其 实体类字段为普通类型的情况
     * 扩展: 可以在判断之前做一次转换
     *
     * @param obj
     * @return Type
     */
    private static Object isFormatCheckObjectType(Object obj) {
        obj = fromtTypeObject(obj);
        Object type = null;
        if (obj instanceof Number) {
            type = obj;
        } else if (obj instanceof Boolean) {
            return obj;
        } else if (null == obj) {
            type = "null";
        } else if (obj instanceof String) {
            type = "\"" + obj + "\"";
        } else {
            // 不是这4种类型就转为 str 来拼接
            type = "\"" + obj + "\"";
            //throw new  RuntimeException("参数转换超出范围");
        }
        return type;
    }

    /**
     * 处理8大基本数据类型的包装类转换
     * 整数: byte,int,short,long
     * 浮点: float,double
     * 布尔:boolean
     * 字符:char -- 没有包装类
     *
     * @param obj
     * @return
     */
    private static Object fromtTypeObject(Object obj) {

        Class<?> aClass = obj.getClass();
        if (aClass == byte.class) {
            return new Byte(obj.toString());
        } else if (aClass == int.class) {
            return new Integer(obj.toString());
        } else if (aClass == short.class) {
            return new Short(obj.toString());
        } else if (aClass == long.class) {
            return new Long(obj.toString());
        } else if (aClass == float.class) {
            return new Float(obj.toString());
        } else if (aClass == double.class) {
            return new Float(obj.toString());
        }
        else if (aClass == boolean.class) {
            return new Boolean(obj.toString());
        }
        else if (aClass == char.class) {
            return new Character(obj.toString().charAt(0));
        }
        return null;
    }


}
